#include "gtest/gtest.h"

#include "ObjectTest.h"
#include "helper/ScopedMemPtr.h"
class PointerTest : public ObjectTest {
public:
    void SetUp() override{
        ObjectTest::SetUp();
        i = 100;
        j = 200;
    }
protected:
    int i;
    int j;
};

using namespace helper;
using namespace object;

TEST_F(PointerTest, testCreateWithObjectFactory){
    const void * expect = &i;
    ScopedMemPtr<Pointer> pointer(getObjectFactory()->createPointer(expect));
    ASSERT_EQ(expect, pointer->get());
}



#include "helper/unittest/Tracer.h"
struct Key {
    Key(int k , int v):k(k), v(v){
        TRACER.reset();
    }
    Key():k(0), v(0){
        TRACER.reset();
    }
    int k;
    int v;
    void print() { 
        TRACER.method("print");
    }
    void print() const { 
        TRACER.methodConst("print");
    }

};

TEST_F(PointerTest, testConstPtr){
    EXPECT.reset().method("print").methodConst("print");

    const Key ckey;
    ScopedMemPtr<Pointer> ptr(getObjectFactory()->createPointer(&ckey));
    static_cast<Key*>(ptr->get())->print();
    static_cast<const Key*>(ptr->get())->print();
    ASSERT_EQ(EXPECT, TRACER);
}

//std::pair<> Hash->getPointer() hash->insertPointer(key, void*)
TEST_F(PointerTest, testPtrInHash){
    ScopedMemPtr<Hash> hash = getObjectFactory()->createHash();

    const char *key = "key";
    ScopedMemPtr<Key> preal = new Key(1, 1);// NOTE: for auto free the key, only for TC
    { //inset  && get
        hash->insertPointer(key, preal.get());

        auto pair = hash->getPointer(key);
        ASSERT_TRUE(pair.first);
        ASSERT_EQ(preal.get(), pair.second);
    }

    { //remove
        auto * ppair = hash->get(key); // return ptr to pair.second
        ScopedMemPtr<Object> ptr = hash->remove(key);
        ASSERT_TRUE(*ppair == ptr.get());

        ASSERT_EQ(0ul, hash->size());
    }
}
TEST_F(PointerTest, testPtrInArray){
    ScopedMemPtr<Array> array = getObjectFactory()->createArray();
    ScopedMemPtr<Key> preal = new Key(2, 2);
    { //append & get
        ASSERT_EQ(0, array->appendPointer(preal.get()));
        ASSERT_EQ(1ul, array->size());

        auto pair = array->getPointer(0);
        ASSERT_TRUE(pair.first);
        ASSERT_EQ(preal.get(), pair.second);
    }

    { // remove
        auto * ppair = array->get(0);
        ScopedMemPtr<Object> ptr = array->remove(0);
        ASSERT_TRUE(*ppair == ptr);

        ASSERT_EQ(0ul, array->size());
    }
}
